package net.kaaass.poplan.ingress.entities;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

import net.kaaass.poplan.ingress.TooMuchLinksException;
import net.kaaass.poplan.util.EvilTransform;

import com.mapdigit.gis.geometry.GeoLatLng;

/**
 * 记录Portal的数据
 * 
 * @author KAAAsS
 */
public class Portal {
	
	/**
	 * 阵营，抵抗军
	 */
	public static final int RESISTANCE = 0;
	
	/**
	 * 阵营，启蒙军
	 */
	public static  final int ENLIGHTENED = 1;
	
	/**
	 * 未占领
	 */
	public static  final int UNCAPTURE = -1;

	/**
	 * 记录Portal的真实位置
	 */
	private GeoLatLng oPos;
	/**
	 * 记录Portal的处理后位置
	 */
	private GeoLatLng pos;
	/**
	 * 记录Portal所属阵营 Available value: 
	 * Portal.RESISTANCE or Portal.ENLIGHTENED or Portal.UNCAPTURE
	 */
	private int camp;
	/**
	 * 存储po的等级
	 */
	private int level = 0;
	/**
	 * 用于记录Portal的Res
	 */
	private List<ResonatorItem> resonators;
	/**
	 * 用于记录Portal的Mod
	 */
	private List<ModItem> mods;
	/**
	 * 用于记录Portal向外的links
	 */
	private List<Link> outLinks = new ArrayList<Link>();
	/**
	 * 用于记录Portal被链接的links
	 */
	private List<Link> inLinks = new ArrayList<Link>();
	/**
	 * 用于记录Portal的cf
	 */
	private List<CField> fields = new ArrayList<CField>();
	/**
	 * 存储拥有玩家的ID
	 */
	private String owner = "Player";

	Portal(GeoLatLng loc, int camp) {
		this(loc, camp, new ArrayList<ResonatorItem>(8),
				new ArrayList<ModItem>(4));
	}

	public Portal(GeoLatLng loc, int camp, List<ResonatorItem> resonators,
			List<ModItem> mods) {
		this.oPos = loc;
		// Cause we're all RESISTANCE www
		this.camp = camp >= 0 && camp <= 1 ? camp : RESISTANCE;
		this.resonators = resonators;
		this.mods = mods;
		this.updateData();
	}

	/**
	 * 该方法用于更新&计算po的数据
	 */
	private void updateData() {
		/*
		 * 火星坐标系转换
		 */
		this.pos = EvilTransform.transToMars(this.oPos);
		/*
		 * 计算po等级
		 */
		this.resonators.forEach(res -> this.level += res.level); // 遍历累加res等级
		this.level = this.level / 8; // 平均地板除
	}

	/**
	 * 获得一个po的经度
	 * 
	 * @return 经度
	 */
	public double getLatitude() {
		return this.pos.lat();
	}

	/**
	 * 获得一个po纬度
	 * 
	 * @return 纬度
	 */
	public double getLongitude() {
		return this.pos.lng();
	}

	/**
	 * 获得一个po的位置信息
	 * 
	 * @return po的位置信息
	 */
	public GeoLatLng getLocation() {
		return this.pos;
	}

	/**
	 * 获得一个po的绝对位置信息(处理前)
	 * 
	 * @return po的绝对位置信息
	 */
	public GeoLatLng getAbsoluteLocation() {
		return this.oPos;
	}

	/**
	 * 获得一个po的阵营 Available value: Portal.RESISTANCE or Portal.ENLIGHTENED
	 * 
	 * @return po阵营
	 */
	public int getCamp() {
		return this.camp;
	}

	/**
	 * 获得一个po等级
	 * 
	 * @return po等级
	 */
	public int getLevel() {
		return this.level;
	}

	/**
	 * 获得一个po所有的Res
	 * 
	 * @return po所有的Res
	 */
	public List<ResonatorItem> getResonator() {
		return this.resonators;
	}

	/**
	 * 获得一个po所有的Mods
	 * 
	 * @return po所有的Mods
	 */
	public List<ModItem> getMods() {
		return this.mods;
	}

	/**
	 * 获得一个po所属玩家id
	 * 
	 * @return po所属玩家id
	 */
	public String getOwner() {
		return this.owner;
	}

	/**
	 * 取po最大link距离
	 * 
	 * @return 最大link距离(m)
	 */
	public int getLinkLimit() {
		switch (this.level) {
		case 1:
			return 160;
		case 2:
			return 1280;
		case 3:
			return 12960;
		case 4:
			return 40960;
		case 5:
			return 100000;
		case 6:
			return 207360;
		case 7:
			return 384160;
		case 8:
			return 655360;
		}
		return -1;
	}

	/**
	 * 是否potal与指定po有link
	 * 
	 * @param desPo
	 *            目标po
	 * @return 是否
	 */
	public boolean with(Portal desPo) {
		return this.outLinks.contains(new Link(this, desPo))
				|| desPo.outLinks.contains(new Link(desPo, this));
	}

	/**
	 * 向指定po创建link
	 * 
	 * @param desPo
	 *            目标po
	 * @return 形成的link
	 * @throws TooMuchLinksException
	 */
	public Link linkTo(Portal desPo) throws TooMuchLinksException {
		// 判断link数是否超出限制
		if (this.outLinks.size() >= 8)
			throw new TooMuchLinksException("Portal向外link数不能超过8！");
		// 创建连接
		Link l = new Link(this, desPo);
		this.outLinks.add(l);
		desPo.inLinks.add(l);
		// 判断是否形成cf
		Consumer<Link> buildCF = el -> {
			if (el.poB.with(desPo)) {
				this.fields.add(new CField(this, el.poB, desPo));
			}
		};
		this.outLinks.forEach(buildCF);
		this.inLinks.forEach(buildCF);
		return l;
	}

	/**
	 * 用于存储谐振器数据
	 * 
	 * @author KAAAsS
	 */
	public static class ResonatorItem {
		/**
		 * 存储Res的等级
		 */
		public int level = 0;
		/**
		 * po的电量
		 */
		public int energy = 0;
		/**
		 * 存储拥有玩家的ID
		 */
		public String owner = "Player";

		public ResonatorItem(int level) {
			this.level = level;
		}
	}

	/**
	 * 用于存储各类Mod数据
	 * 
	 * @author KAAAsS
	 */
	public static class ModItem {
		/**
		 * 存储mod的等级
		 */
		public int level = 0;
		/**
		 * 存储拥有玩家的ID
		 */
		public String owner = "Player";
	}
}
